package com.dilean.common.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.dilean.api.dao.AttributeDAO;
import com.dilean.api.dao.PersonDAO;
import com.dilean.api.model.Attribute;
import com.dilean.api.model.AttributeValue;
import com.dilean.api.model.AttributeValueFactory;
import com.dilean.api.model.Person;
import com.dilean.common.api.DataImporter;
import com.dilean.impl.model.PersonImpl;

import static com.dilean.common.DileanAttrTypes.*;

@Component
public class DataImporterExcel implements DataImporter {

	@Autowired
	private AttributeValueFactory attrValueFactory;

	@Autowired
	private PersonDAO personDAO;
	
	@Autowired
	private AttributeDAO attributeDAO;

	private Map<String, Integer> configuration;
	private Map<Integer, Integer> order;
	private static final Log log = LogFactory.getLog(DataImporterExcel.class);

	@Override
	public synchronized Map<String, Integer> configurate() 
	{
		if (configuration != null)
			return configuration;
			
		HashMap<String, Integer> configuration = new HashMap<String, Integer>();
		try {
			XMLConfiguration config = new XMLConfiguration("configuration.xml");
			Object prop = config.getProperty("column.name");
			int size = 0;
			if (prop instanceof Collection) {
				size = ((Collection<?>) prop).size();
			}

			for (int i = 0; i < size; i++) {
				String name = (String) config.getProperty("column(" + i + ").name");
				Integer attributeId = Integer.valueOf((String) config.getProperty("column(" + i + ").attributeId"));
				configuration.put(name, attributeId);
			}
		} catch (ConfigurationException e) {
			log.error("File not found", e);
			throw new RuntimeException("File was not found", e);
		}
		
		this.configuration = Collections.unmodifiableMap(configuration);
		
		return configuration;
	}

	@Override
	public void convert(File fileToProcess) 
	{
		FileInputStream file;
		try {
			file = new FileInputStream(fileToProcess);
			XSSFWorkbook workbook = new XSSFWorkbook(file);
			XSSFSheet sheet = workbook.getSheetAt(0);
			Iterator<Row> rowIterator = sheet.iterator();
			Row row;
			order = new HashMap<Integer, Integer>();
			
			if (rowIterator.hasNext()) {
				row = rowIterator.next();
				int i = 0;

				for (Cell cell : row) {
					String header = cell.getStringCellValue();
					order.put(i, configuration.get(header));
					i++;
				}
			}
			
			int num = 0;
			while (rowIterator.hasNext()) {
				row = rowIterator.next();
				Person person = new PersonImpl();
				person.setName("person" + num);

				person = personDAO.save(person);
				Integer personId = person.getId();
				
				int i = 0;
				for (Cell cell : row) {
					Integer attrId = order.get(i);
					Attribute attribute = attributeDAO.findById(attrId);
					Object data = null;

					if (attribute.getAttributeType().getId() == ATTR_TYPE_ID_DATE) {
						data = cell.getDateCellValue();
					}
					else {
						cell.setCellType(Cell.CELL_TYPE_STRING);
						data = cell.getStringCellValue();
					}
					System.out.println(data.toString());
					AttributeValue<?> attrValue = attrValueFactory
							.createValueFromString(personId, attrId, data);
					person.setParameterForUpdate(attrId, attrValue);
					i++;
				}
				personDAO.save(person);
				num++;
			}

		} 
		catch (FileNotFoundException e)
		{
			log.error("File not found", e);
		} 
		catch (IOException e) 
		{
			log.error("IOException", e);
		}
	}

}
